#include <Python.h>
#include <stdlib.h>
#include "gtktester.h"
#include "gtktester_constants.h"
#include "gtktestermodule.h"
#include <gtk/gtk.h>

#define DEFAULT_SUITE_FILENAME "testsuite"

char gtktester_command_error[1024];

/* Our static test case variables */
static gchar *filename = NULL;
FILE *suite_file = NULL;
static gchar *tcase = NULL;
static gboolean notests = FALSE;

static GOptionEntry entries[] =
{
  { "file", 'f', 0, G_OPTION_ARG_STRING, &filename, "File that contains the test suite", "foo" },
  { "case", 'c', 0, G_OPTION_ARG_STRING, &tcase, "Test to perform", "N" },
  { "notests", 'n', 0, G_OPTION_ARG_NONE, &notests, "Disable testing, run as a normal application.  You can also recompile with -DNOTESTS", NULL},
  { NULL }
};

/* Execute one command/assertion of the test case */
static gboolean gtktester_run (gpointer dummy)
{
	PyObject *pModule, *pFunc, *pValue;
	if (notests) return FALSE;
	if (!filename) {
		filename = strdup(DEFAULT_SUITE_FILENAME);
	}
	if (!tcase) {
		printf("No test case chosen.  To run all tests use the gtktester_runsuite.sh script\n");
		gtk_main_quit();
		return FALSE;
	}
	else if (!strcasecmp (filename + strlen (filename) - 3, ".py")) {
		/* Chop off the trailing .py */
		filename[strlen(filename)-3] = 0;
	}
	pModule = PyImport_ImportModule(filename);

	if (pModule != NULL) {
		pFunc = PyObject_GetAttrString(pModule, tcase);
		/* pFunc is a new reference */

		if (pFunc && PyCallable_Check(pFunc)) {
			pValue = PyObject_CallObject(pFunc, NULL);
			if (pValue != NULL) {
				if (PyObject_Compare (pValue, Py_BuildValue ("i", GTKTESTER_SUCCESS))) {
					if (!PyObject_Compare (pValue, Py_BuildValue ("i", GTKTESTER_FAILURE)))
						printf("F");
					else if (!PyObject_Compare (pValue, Py_BuildValue ("i", GTKTESTER_ABORT)))
						printf("A");
					else
						/* case GTKTESTER_TEST_FINISHED: */
						printf(".");
				}
				Py_DECREF(pValue);
			}
			else {
				Py_DECREF(pFunc);
				Py_DECREF(pModule);
				PyErr_Print();
				fprintf(stderr,"Call failed\n");
			}
		}
		else {
			if (PyErr_Occurred())
				PyErr_Print();
			fprintf(stderr, "Cannot find function \"test\"\n");
		}
		Py_XDECREF(pFunc);
		Py_DECREF(pModule);
	}
	else {
		PyErr_Print();
		fprintf(stderr, "Failed to load \"%s\"\n", filename);
	}
	gtk_main_quit();
	Py_Finalize();
	return TRUE;
}

void gtktester_init(int argc, char *argv[])
{
	if (!gtktester_init_check (argc, argv))
		exit (2);
}

int gtktester_init_check(int argc, char *argv[])
{
#ifndef NOTESTS
	GError *error = NULL;
	GOptionContext *context;
	int handle, i;
	char *orig_path, *new_path;
	char **av = (char**)malloc(argc * sizeof(char*));

	gtktester_command_error[0] = 0;

	for (i = 0; i < argc; i++)
		av[i] = g_strdup(argv[i]);

	context = g_option_context_new ("- A test framework for precisely this!");
	g_option_context_add_main_entries (context, entries, NULL);
	g_option_context_add_group (context, gtk_get_option_group (TRUE));
	g_option_context_parse (context, &argc, &av, &error);

	for (i = 0; i < argc; i++)
		g_free(av[i]);
	g_free(av);

	handle = g_idle_add (gtktester_run, NULL);

	/* Set up PYTHONPATH to find testsuite.py */
	orig_path = getenv ("PYTHONPATH");
	if (orig_path) {
		new_path = (char*)malloc(strlen(orig_path)+4);
		strcpy (new_path, ".:");
		strcat (new_path, orig_path);
	}
	else {
		new_path = strdup(".");
	}
	setenv ("PYTHONPATH", new_path, TRUE);

	Py_Initialize();
	initgtktester(); /* Initialize the Python module to have access to commands and assertions within tests */
#endif
	return 1;
}

